package com.xueshandai.db.migration.persistence.implement;

import com.xueshandai.db.migration.mode.ColumnData;
import com.xueshandai.db.migration.mode.LineData;
import com.xueshandai.db.migration.mode.MetaData;
import com.xueshandai.db.migration.mode.config.FieldMap;
import com.xueshandai.db.migration.mode.config.TableMap;
import com.xueshandai.db.migration.persistence.Access;

import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by Zetas on 2014/12/25.
 */
public class AccessMySQLImpl implements Access {

    private final int maxValueSize = 5000;                       //单次最大插入数据量

    private TableMap tableMap;
    private StringBuffer columnNames = new StringBuffer();        //待插入表的字段名
    private List<String> columnValuesList = new ArrayList<String>();        //待插入表的单条数据值
    private Connection connection;
    private PreparedStatement preparedStatement;
    private ResultSetMetaData resultSetMetaData;
    private ResultSet resultSet;
    private List<MetaData> metaDataList;

    public AccessMySQLImpl(Connection connection, TableMap tableMap) {
        this.tableMap = tableMap;

        List<FieldMap> fieldMapList = tableMap.getFieldMapList();
        for (int i=0; i<fieldMapList.size(); i++) {
            FieldMap fieldMap = fieldMapList.get(i);
            String newField = fieldMap.getNewField();
            if ( i < fieldMapList.size()-1 ) {
                columnNames.append("`"+newField+"`,");
            } else {
                columnNames.append("`"+newField+"`");
            }
        }
        logger.info("初始化待插入字段完成："+columnNames.toString());

        this.connection = connection;
        this.metaDataList = new LinkedList<MetaData>();
        try {
            this.preparedStatement = connection.prepareStatement("select * from "+tableMap.getNewTableName());
            resultSet = preparedStatement.executeQuery();
            resultSetMetaData = resultSet.getMetaData();
            int columnCount = resultSetMetaData.getColumnCount();
            for (int i=1; i<columnCount; i++) {
                MetaData metaData = new MetaData();
                metaData.setColumnClassName(resultSetMetaData.getColumnClassName(i));
                metaData.setColumnTypeName(resultSetMetaData.getColumnTypeName(i));
                metaData.setColumnName(resultSetMetaData.getColumnName(i));
                metaData.setColumnDisplaySize(resultSetMetaData.getColumnDisplaySize(i));
                metaDataList.add(metaData);
            }
            logger.info(tableMap.getNewTableName()+"表字段元数据初始化完成");
        } catch (SQLException e) {
            logger.error(e);
        }
    }

    @Override
    public boolean next() {
        boolean result = false;
        try {
            result = resultSet.next();
        } catch (SQLException e) {
            logger.error(e);
        }

        return result;
    }

    @Override
    public LineData readLine() {
        LineData lineData = new LineData();
        try {
            for (MetaData metaData : metaDataList) {
                String data = resultSet.getString(metaData.getColumnName());
                ColumnData columnData = new ColumnData();
                columnData.setMetaData(metaData);
                columnData.setData(data);
                lineData.add(columnData);
            }
        } catch (SQLException e) {
            logger.error(e);
        }
        return lineData;
    }

    @Override
    public void writeLine(LineData lineData) {
        StringBuffer columnValues = new StringBuffer();

        List<FieldMap> fieldMapList = tableMap.getFieldMapList();

        for (int i=0; i<fieldMapList.size(); i++) {
            FieldMap fieldMap = fieldMapList.get(i);
            String oldField = fieldMap.getOldField();
            String value = lineData.getValue(oldField);

            //组装结果数据，分为两种情况，有值或者值为空
            if ( i < fieldMapList.size()-1 ) {
                if ( value == null ) {
                    columnValues.append(value+',');
                } else {
                    columnValues.append("'"+value+"'"+',');
                }
            } else {
                if ( value == null ) {
                    columnValues.append(value);
                } else {
                    columnValues.append("'"+value+"'");
                }
            }
        }
        columnValuesList.add(columnValues.toString());

        try {
            if (columnValuesList.size() >= maxValueSize) {
                StringBuffer values = new StringBuffer();
                for (int i = 0; i < columnValuesList.size(); i++) {
                    if (i < columnValuesList.size() - 1) {
                        values.append("(" + columnValuesList.get(i) + "),");
                    } else {
                        values.append("(" + columnValuesList.get(i) + ")");
                    }
                }

                String sqlStr = "insert into " + tableMap.getNewTableName() + " (" + columnNames.toString() + ") values " + values.toString();
                int count = preparedStatement.executeUpdate(sqlStr);

                columnValuesList.clear();
                logger.info(tableMap.getNewTableName() + "表成功插入" + count + "条数据");
            }
        }catch (SQLException e) {
            logger.error(tableMap.getNewTableName()+"表插入数据失败", e);
        }
    }

    @Override
    public void destroy() {
        try {
            if (columnValuesList.size() > 0 ) {
                StringBuffer values = new StringBuffer();
                for (int i = 0; i < columnValuesList.size(); i++) {
                    if (i < columnValuesList.size() - 1) {
                        values.append("(" + columnValuesList.get(i) + "),");
                    } else {
                        values.append("(" + columnValuesList.get(i) + ")");
                    }
                }

                String sqlStr = "insert into " + tableMap.getNewTableName() + " (" + columnNames.toString() + ") values " + values.toString();
                int count = preparedStatement.executeUpdate(sqlStr);

                columnValuesList.clear();
                logger.info(tableMap.getNewTableName() + "表成功插入" + count + "条数据");
            }
        }catch (SQLException e) {
            logger.error(tableMap.getNewTableName()+"表插入数据失败", e);
        }

        if ( resultSet != null ) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                logger.error(e);
            }
        }
        if ( preparedStatement != null ) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                logger.error(e);
            }
        }
        if ( connection != null ) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.error(e);
            }
        }
    }
}
